/**
 * Copyright 2005 The Apache Software Foundation
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.edi.db.dao;

import java.sql.SQLException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.edi.db.EdiCallableStatement;
import com.edi.db.PreparedEql;
import com.edi.db.Session;
import com.edi.db.TransactionWrapper;
import com.edi.db.table.TableEntity;
import com.edi.db.util.SessionUtil;

/**
 * DAO
 * 
 * 
 */
public class EdiDAO {
	private SessionUtil sessionUtil;

	private static final Log log = LogFactory.getLog(EdiDAO.class);

	public EdiDAO(SessionUtil sessionUtil)throws EdiDAOException {
		if (sessionUtil == null){
			throw new EdiDAOException("SessionUtil is null");
		}
		this.sessionUtil = sessionUtil;
	}

	public void excuteSql(String sql) throws EdiDAOException{
		Session session = sessionUtil.getSession();
		try {
			sessionUtil.beginTransaction();
			session.excuteSql(sql);
			sessionUtil.commitTransaction();
		} catch (SQLException e) {
			sessionUtil.rollbackTransaction();
			throw new EdiDAOException ("excute sql occur Error",e);			
		} finally {
			sessionUtil.closeSession();
		}
	}
	
	public void createTable(TableEntity tableEntity)throws EdiDAOException{
		Session session = sessionUtil.getSession();
		try {
//			log.debug(" enter createTable");
			sessionUtil.beginTransaction();
			session.createTable(tableEntity);
//			log.debug(" end createTable");
			sessionUtil.commitTransaction();
		} catch (SQLException e) {
			sessionUtil.rollbackTransaction();
			e.printStackTrace();
			throw new EdiDAOException ("create table occur Error",e);			
		} finally {
			sessionUtil.closeSession();
		}

	}

	public void excuteEql(String eql) throws EdiDAOException{
		Session session = sessionUtil.getSession();
		try {
			sessionUtil.beginTransaction();
			session.executeEql(eql);
			sessionUtil.commitTransaction();
		} catch (SQLException e) {
			sessionUtil.rollbackTransaction();
			throw new EdiDAOException("execute eql occur Error",e);
		} finally {
			sessionUtil.closeSession();
		}
	}

	public void save(TableEntity tableEntity) throws EdiDAOException {
		Session session = sessionUtil.getSession();
		try {
			sessionUtil.beginTransaction();
			session.save(tableEntity);
			sessionUtil.commitTransaction();
		} catch (SQLException e) {
			sessionUtil.rollbackTransaction();
			throw new EdiDAOException("save table occur Error",e);
		} finally {
			sessionUtil.closeSession();
		}

	}
	
	/**
	 * 执行事务动作
	 * @param transactionWrappers 事务动作集合
	 * @throws EdiDAOException
	 */
	public void execTansaction(List<TransactionWrapper> transactionWrappers)throws EdiDAOException{
		Session session = sessionUtil.getSession();
		
		try{
			sessionUtil.beginTransaction();
			
			for(TransactionWrapper transWrapper : transactionWrappers){
				if (transWrapper.getTansaction() instanceof PreparedEql){//执行EQL语句
					session.executePreparedEql((PreparedEql)transWrapper.getTansaction());
				}else if (transWrapper.getTansaction() instanceof Map){//执行表操作
					Map<String,TableEntity> tableMaps = (Map<String,TableEntity>)transWrapper.getTansaction();
					if (tableMaps.get("remove")!=null && tableMaps.get("remove").getRows().size()>0)
						session.delete(tableMaps.get("remove"));
					if (tableMaps.get("add") != null && tableMaps.get("add").getRows().size()>0)
						session.save(tableMaps.get("add"));
					if (tableMaps.get("update") != null && tableMaps.get("update").getRows().size()>0)
						session.update(tableMaps.get("update"));
				}
			}
			
			sessionUtil.commitTransaction();
		}catch (SQLException e) {
			sessionUtil.rollbackTransaction();
			e.printStackTrace();
			throw new EdiDAOException("执行事务发生错误：",e);
		} finally {
			sessionUtil.closeSession();
		}
	}
	
	public void commitTables(Map<String,TableEntity> tableMaps) throws EdiDAOException{
		Session session = sessionUtil.getSession();
		try {
			sessionUtil.beginTransaction();
			if (tableMaps.get("remove").getRows().size()>0)
				session.delete(tableMaps.get("remove"));
			if (tableMaps.get("add").getRows().size()>0)
				session.save(tableMaps.get("add"));
			if (tableMaps.get("update").getRows().size()>0)
				session.update(tableMaps.get("update"));
			sessionUtil.commitTransaction();
		} catch (SQLException e) {
			sessionUtil.rollbackTransaction();
			e.printStackTrace();
			throw new EdiDAOException("save table occur Error",e);
		} finally {
			sessionUtil.closeSession();
		}
	}

	public void update(TableEntity tableEntity) throws EdiDAOException {
		Session session = sessionUtil.getSession();
		try {
			sessionUtil.beginTransaction();
			session.update(tableEntity);
			sessionUtil.commitTransaction();
		} catch (SQLException e) {
			sessionUtil.rollbackTransaction();
			throw new EdiDAOException("update table occur Error",e);
		} finally {
			sessionUtil.closeSession();
		}

	}

	public TableEntity querySql(String sql,Integer start,Integer pageSize)throws EdiDAOException  {
		TableEntity entity = null;
		Session session = sessionUtil.getSession();
		try {
//			sessionUtil.beginTransaction();
			entity = session.querySql(sql,start,pageSize);
//			sessionUtil.commitTransaction();
		} catch (SQLException e) {
//			sessionUtil.rollbackTransaction();
			throw new EdiDAOException("query sql occur Error",e);
		} finally {
			sessionUtil.closeSession();
		}

		return entity;
	}
	
	public TableEntity querySql(String sql) throws EdiDAOException{
		return this.querySql(sql,null,null);
	}
	
	public TableEntity queryPreparedEql(PreparedEql preparedEql) throws EdiDAOException{
		TableEntity entity = null;
		Session session = sessionUtil.getSession();
		if (session == null)
			throw new EdiDAOException("-------------------发生异常，session为空");
		try{
			entity = session.queryPreparedEql(preparedEql);
		}catch(SQLException e){
			throw new EdiDAOException("query preparedeql occur Error",e);
		}finally{
			sessionUtil.closeSession();
		}
		
		return entity;
	}
	
	public void executePreparedEql(PreparedEql preparedEql) throws EdiDAOException{
		
		Session session = sessionUtil.getSession();
		try {
			sessionUtil.beginTransaction();
			session.executePreparedEql(preparedEql);
			sessionUtil.commitTransaction();
		} catch (SQLException e) {
			sessionUtil.rollbackTransaction();
			throw new EdiDAOException ("excute preparedEql occur Error",e);			
		} finally {
			sessionUtil.closeSession();
		}
		
	}
	
	/**
	 * 执行无返回结果集的存储过程
	 * @param proc
	 * @throws EdiDAOException
	 */
	public Map<Integer,Object> executeProc(EdiCallableStatement proc) throws EdiDAOException{
		Session session = sessionUtil.getSession();
		Map<Integer,Object> outParamValues = new HashMap<Integer,Object>();
		try{
			//sessionUtil.beginTransaction();
			outParamValues = session.executeProc(proc);
			//sessionUtil.commitTransaction();
		}catch(SQLException e){
		//	sessionUtil.rollbackTransaction();
			throw new EdiDAOException ("存储过程执行错误",e);
		}finally{
			sessionUtil.closeSession();
		}
		
		return outParamValues;
	}
	
	/**
	 * 执行具有返回结果集和输出参数的存储过程
	 * @param proc
	 * @throws EdiDAOException
	 */
	public TableEntity queryProc(EdiCallableStatement proc,Map<Integer,Object> outParamValues) throws EdiDAOException{
		TableEntity entity = null;
		Session session = sessionUtil.getSession();
		try{
			//sessionUtil.beginTransaction();
			entity = session.queryProc(proc,outParamValues);
			//sessionUtil.commitTransaction();
		}catch(SQLException e){
			//sessionUtil.rollbackTransaction();
			throw new EdiDAOException("存储过程执行错误",e);
		}finally{
			sessionUtil.closeSession();
		}
		return entity;
	}
	
	/**
	 * 执行具有返回结果集的存储过程
	 * @param proc
	 * @return
	 * @throws EdiDAOException
	 */
	public TableEntity queryProc(EdiCallableStatement proc) throws EdiDAOException{
		TableEntity entity = null;
		Session session = sessionUtil.getSession();
		try{
			//sessionUtil.beginTransaction();
			entity = session.queryProc(proc);
			//sessionUtil.commitTransaction();
		}catch(SQLException e){
			//sessionUtil.rollbackTransaction();
			throw new EdiDAOException("存储过程执行错误",e);
		}finally{
			sessionUtil.closeSession();
		}
		return entity;
	}


	public TableEntity queryEql(String eql,Integer start,Integer pageSize)throws EdiDAOException {
		TableEntity entity = null;
		Session session = sessionUtil.getSession();
		try {
//			sessionUtil.beginTransaction();
			entity = session.queryEql(eql,start,pageSize);
//			sessionUtil.commitTransaction();
		} catch (SQLException e) {
//			sessionUtil.rollbackTransaction();
			throw new EdiDAOException("query eql occur Error",e);
		} finally {
			sessionUtil.closeSession();
		}

		return entity;
	}
	
	public TableEntity queryEql(String eql) throws EdiDAOException{
		return this.queryEql(eql, null, null);
	}
	
	public boolean hasTable(String tableName) throws EdiDAOException{
		Session session = sessionUtil.getSession();
		boolean result = false;
		try {
//			sessionUtil.beginTransaction();
			result = session.hasTable(tableName);
			
//			sessionUtil.commitTransaction();
		} catch (SQLException e) {
//			sessionUtil.rollbackTransaction();
			e.printStackTrace();
			throw new EdiDAOException("hasTable occured error",e);
		} finally {
			sessionUtil.closeSession();
		}
		return result;
	}
	
	public boolean createBaseTable(TableEntity tableEntity)throws EdiDAOException{
		Session session = sessionUtil.getSession();
		boolean result = false;
		try {
//			sessionUtil.beginTransaction();
			session.createBaseTable(tableEntity);
			result = true;
//			sessionUtil.commitTransaction();
		} catch (SQLException e) {
//			sessionUtil.rollbackTransaction();
			throw new EdiDAOException("hasTable occured error",e);
		} finally {
			sessionUtil.closeSession();
		}
		return result;
	}
	
	public SessionUtil getSessionUtil()throws EdiDAOException{
		return sessionUtil;
	}
}
